package org.groovymud.shell.telnetd;

import java.io.IOException;

import net.wimpi.telnetd.net.Connection;
import net.wimpi.telnetd.net.ConnectionData;
import net.wimpi.telnetd.net.ConnectionEvent;

import org.apache.log4j.Logger;
import org.groovymud.object.registry.Registry;
import org.groovymud.shell.Shell;
import org.groovymud.shell.io.TerminalIO;
import org.groovymud.shell.io.TerminalIOFactory;
import org.springframework.context.ApplicationContext;

/**
 * horrible fudge to make spring and telnetd more compatible function here
 * 
 * the shell bridge basically enables spring to define telnetd shells.
 * 
 * 
 */
public abstract class ShellBridge implements Shell {

	private final static Logger logger = Logger.getLogger(ShellBridge.class);

	private static ApplicationContext context;

	private TerminalIO terminalIO;
	private Connection connection;

	private final Registry registry;
	private final TerminalIOFactory ioFactory;

    public ShellBridge(Registry registry, TerminalIOFactory ioFactory) {
        this.registry = registry;
        this.ioFactory = ioFactory;
    }

    public static void setApplicationContext(ApplicationContext context) {
		ShellBridge.context = context;
	}

	public static ApplicationContext getApplicationContext() {
		return ShellBridge.context;
	}

	public void connectionIdle(ConnectionEvent ce) {
		try {
			getTerminalIO().write("CONNECTION_IDLE");

			getTerminalIO().flush();
		} catch (IOException e) {
			logger.error(e, e);
		}
	}

	// this implements the ConnectionListener!
	public void connectionTimedOut(ConnectionEvent ce) {
		try {
			getTerminalIO().write("CONNECTION_TIMEDOUT");
			getTerminalIO().flush();
			// close connection
			getTerminalIO().close();
		} catch (Exception ex) {
			logger.error("connectionTimedOut()", ex);
		}
	}

	public void connectionLogoutRequest(ConnectionEvent ce) {
		try {
			getTerminalIO().write("CONNECTION_LOGOUTREQUEST");
			getTerminalIO().flush();
		} catch (IOException e) {
			logger.error(e, e);
		}

	}

	public void connectionSentBreak(ConnectionEvent ce) {
		try {
			getTerminalIO().write("CONNECTION_BREAK");
			getTerminalIO().flush();
		} catch (IOException e) {
			logger.error(e, e);
		}

	}

	public void run(Connection con) {
		TerminalIO io = ioFactory.createTerminalIO(con);
		setTerminalIO(io);
		this.connection = con;
		con.addConnectionListener(this);
		ConnectionData connectionData = con.getConnectionData();
		try {
			io.writeln("term type:" + connectionData.getNegotiatedTerminalType());
		} catch (IOException e) {
			logger.error(e, e);
		}
		doRun();
	}

	

	public TerminalIO getTerminalIO() {
		return terminalIO;
	}

	public void setTerminalIO(TerminalIO terminalIO) {
		this.terminalIO = terminalIO;
	}

	
	/**
	 * @return the connection
	 */
	protected Connection getConnection() {
		return connection;
	}

	public boolean isConnectionActive(){
		return connection.isActive();
	}

	
	/**
	 * @return the registry
	 */
	public Registry getRegistry() {
		return registry;
	}

    public TerminalIOFactory getIoFactory() {
        return ioFactory;
    }

}
